package bebetes;

/*
 * Bebete.java
 */

/**
 *
 * @author  collet  (d'après L. O'Brien, C. Reynolds & B. Eckel)
 * @version 3.0
 */

import java.awt.*;
import java.util.List;
import java.util.Observable;
import java.util.Random;

import fr.unice.plugin.Plugin;

import simu.Actionnable;
import util.DistancesEtDirections;
import visu.Champ;
import visu.Dessinable;
import visu.PerceptionAble;
import visu.Positionnable;

/**
 * Classe representant la bebete
 */
public abstract class BebeteAbstraite extends Observable implements Dessinable, Actionnable, 
														   PerceptionAble, Plugin {

	static float champDeVue = (float) (Math.PI / 4); // En radians
	static int longueurDeVue = 20; // nb de pixel pour la longueur du champ de vision
	private static int nombreBebete = 0;

	protected int x;
	protected int y;
	protected float vitesseCourante; // vitesse en pixels par second
	protected float directionCourante; // en radians [0 - 2 PI[
	protected Color couleur; // Couleur de remplissage
	protected ChampDeBebetes champ; // Le champ
	protected Comportement comportementParDefaut;
	protected Comportement comportementPredateurs;
	protected int numeroBebete; //L'identifiant de la bebete
	protected int energie;
	
	public BebeteAbstraite(ChampDeBebetes c, int x, int y, float dC, float vC, Color col, Comportement compNormal, Comportement compPredateur) 
	{
		Random rand = new Random();
		champ = c;
		this.x = x;
		this.y = y;
		directionCourante = dC;
		vitesseCourante = vC;
		couleur = col;
		comportementParDefaut = compNormal;
		comportementPredateurs = compPredateur;
		numeroBebete = nombreBebete++;
		energie = 90 + rand.nextInt(21);
	}

	/* Definition plus precise de l'action de la bebete */
	
	// modifie les parametres de vitesse et de direction.
	//public abstract void calculeDeplacementAFaire();

	// modifie la position en fonction de vitesse et direction courantes
	//public abstract void effectueDeplacement();

	// Implementation de Actionnable */
	
	/**
	 * Si on a un comportement predateur, lorsque l'energie a atteinds son seuil max
	 * on appel le comportement du predateur
	 * sinon le comportement par defaut
	 */
	public void agit() {
		if(energie > 20 || comportementPredateurs == null)
			comportementParDefaut.agit(this);
		else
			comportementPredateurs.agit(this);
	}
	
	/**
	 * Si on a un comportement predateur, lorsque l'energie a atteinds son seuil max
	 * on calcul le deplacement en fonction du predateur,
	 * sinon du comportement par defaut
	 */
	public void calculeDeplacementAFaire()
	{
		if(energie > 20 || comportementPredateurs == null)
			comportementParDefaut.calculeDeplacementAFaire(this);
		else
			comportementPredateurs.calculeDeplacementAFaire(this);
	}
	
	/**
	 * Si on a un comportement predateur, lorsque l'energie a atteinds son seuil max
	 * on effectur le deplacement en fonction du predateur,
	 * sinon du comportement par defaut
	 */
	public void effectueDeplacement()
	{
		if(energie > 20 || comportementPredateurs == null)
			comportementParDefaut.effectueDeplacement(this);
		else
			comportementPredateurs.effectueDeplacement(this);
	}

	/* Implementation de Dessinable */
	
	public Color getCouleur() {
		return couleur;
	}

	public void setCouleur(Color couleur) {
		this.couleur = couleur;
	}
	
	/**
	 * On dessine la bebete,
	 * si elle est morte on la rend transparente
	 */
	public void seDessine(Graphics g) {
		if(estVivante())
		{
			int CDVDegres = (int) Math.toDegrees(champDeVue);
			g.setColor(couleur);
			g.fillArc(x, y, TAILLEGRAPHIQUE, TAILLEGRAPHIQUE, -(int) Math
					.toDegrees(directionCourante)
					- (CDVDegres / 2), CDVDegres);
		}
		else if(couleur != null)
		{
			g.setColor(null);
			couleur = null;
			nombreBebete--;
		}
		
	}

	/* Implementation de Positionnable */
	
	public int getX() {
		return x;
	}

	public void setX(int x) {
		this.x = x;
	}
	
	public int getY() {
		return y;
	}

	public void setY(int y) {
		this.y = y;
	}
	
	public Champ getChamp() {
		return champ;
	}
	
	/* Implementation de Dirigeable */

	public float getVitesseCourante() {
		return vitesseCourante;
	}
	
	public void setVitesseCourante(float vitesseCourante) {
		this.vitesseCourante = vitesseCourante;
	}

	public float getDirectionCourante() {
		return directionCourante;
	}

	public void setDirectionCourante(float directionCourante) {
		this.directionCourante = directionCourante;
	}

    /* Implementation de PerceptionAble */

	public int getLongueurDeVue() {
		return longueurDeVue;
	}

	public float getChampDeVue() {
		return champDeVue;
	}
	
	public List<Positionnable> getChosesVues() {
		return DistancesEtDirections.getChosesVues(this);
	}
	
	/* changer la longueur et le champ de vue est "static",
	   alors que les consulter se fait par des fonctions membres */
	
	public static void setLongueurDeVue(int lDV) { 
		longueurDeVue = lDV;
	}
	
	public static void setChampDeVue(int cDV) { 
		champDeVue = cDV;
	}
	
	public int getEnergie()
	{
		return energie;
	}
	
	public void setEnergie(int ener)
	{
		energie = ener;
	}
	
	public boolean estVivante()
	{
		return (energie > 0);
	}
	
	public int getNumeroBebete()
	{
		return numeroBebete;
	}
	

	public static int getNombreBebete()
	{
		return nombreBebete;
	}
	
	public Comportement getComportementPredateur()
	{
		return comportementPredateurs;

	}
	
	public Comportement getComportementNormal()
	{
		return comportementParDefaut;

	}

//	 partie propre au la transformation en Plugin

	  public String getName() {
	    return "bebete";
	  }
	
}
